﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

using Orchard.ContentManagement.Drivers;
using EMS.Calendar.Models;
using Orchard.ContentManagement;
using Orchard.ContentManagement.Handlers;
using EMS.Calendar.ViewModels;
using EMS.Calendar.Services;

namespace EMS.Calendar.Drivers {
    public class CalendarDriver : ContentPartDriver<CalendarPart> {
        private ICalendarService _calendarService;

        public CalendarDriver(ICalendarService calendarService) {
            _calendarService = calendarService;
        }

        protected override DriverResult Display(CalendarPart part, string displayType, dynamic shapeHelper) {
            return ContentShape("Parts_Calendar",
                                () => shapeHelper.Parts_Calendar(part)
                                );
        }

        protected override DriverResult Editor(CalendarPart part, dynamic shapeHelper) {
            var calendarViewModel = new CalendarViewModel();
            LoadViewModel(ref calendarViewModel, part);

            return ContentShape("Parts_Calendar_Edit",
                               () => shapeHelper.EditorTemplate(
                                   TemplateName: "Parts.Calendar.Edit",
                                   Model: calendarViewModel,
                                   Prefix: Prefix)
                                );
        }

        protected override DriverResult Editor(CalendarPart part, IUpdateModel updater, dynamic shapeHelper) {
            CalendarViewModel calendarViewModel = new CalendarViewModel();
            
            updater.TryUpdateModel(calendarViewModel, Prefix, null, null);
            LoadPart(ref part, calendarViewModel);
            
            return Editor(part, shapeHelper);
        }

        protected override void Exporting(CalendarPart part, ExportContentContext context) {
            context.Element(part.PartDefinition.Name).SetAttributeValue("EventOccurrence", part.EventOccurrence.ToString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("StartDate", part.StartDate == null ? "" : DateTime.Parse(part.StartDate.ToString()).ToShortDateString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("StartTime", part.StartTime == null ? "" : DateTime.Parse(part.StartTime.ToString()).ToShortTimeString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("EndDate", part.EndDate == null ? "" : DateTime.Parse(part.EndDate.ToString()).ToShortDateString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("EndTime", part.EndTime == null ? "" : DateTime.Parse(part.EndTime.ToString()).ToShortTimeString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("IsAllDayEvent", part.IsAllDayEvent.ToString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("Pattern", part.Pattern.ToString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("PeriodSpan", part.PeriodSpan.ToString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("DayOfPeriod", part.DayOfPeriod.ToString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("DayInstance", part.DayInstance.ToString());
            // Make a csv for dayNamesArray
            string[] dayNamesArray = StaticCalendarServices.GetDayNameArrayFromList(part.DayNames);
            string dayNamesString = "";
            foreach (var dayName in dayNamesArray) {
                dayNamesString += String.Format("{0},", dayName);
            }
            if (dayNamesArray.Count() > 0) {
                dayNamesString = dayNamesString.Substring(0, dayNamesString.Length - 1); // This removes the last comma
            }
            context.Element(part.PartDefinition.Name).SetAttributeValue("DayNames", dayNamesString);
            context.Element(part.PartDefinition.Name).SetAttributeValue("MonthName", part.MonthName.ToString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("RecurrenceEnd", part.RecurrenceEnd.ToString());
            context.Element(part.PartDefinition.Name).SetAttributeValue("NumberOccurrences", part.NumberOccurrences.ToString());
        }

        protected override void Importing(CalendarPart part, ImportContentContext context) {
            var eventOccurrence = context.Attribute(part.PartDefinition.Name, "EventOccurrence");
            if (eventOccurrence != null) {
                EventOccurrenceType tempEventOccurrence;
                if (Enum.TryParse<EventOccurrenceType>(eventOccurrence, out tempEventOccurrence))
                    part.EventOccurrence = tempEventOccurrence;
            }

            var startDate = context.Attribute(part.PartDefinition.Name, "StartDate");
            if (startDate != null) {
                DateTime tempStartDate;
                if (DateTime.TryParse(startDate, out tempStartDate))
                    part.StartDate = tempStartDate;
            }

            var startTime = context.Attribute(part.PartDefinition.Name, "StartTime");
            if (startTime != null) {
                DateTime tempStartTime;
                if (DateTime.TryParse(startTime, out tempStartTime))
                    part.StartTime = tempStartTime;
            }

            var endDate = context.Attribute(part.PartDefinition.Name, "EndDate");
            if (endDate != null) {
                DateTime tempEndDate;
                if (DateTime.TryParse(endDate, out tempEndDate))
                    part.EndDate = tempEndDate;
            }

            var endTime = context.Attribute(part.PartDefinition.Name, "EndTime");
            if (endTime != null) {
                DateTime tempEndTime;
                if (DateTime.TryParse(endTime, out tempEndTime))
                    part.EndTime = tempEndTime;
            }

            var isAllDayEvent = context.Attribute(part.PartDefinition.Name, "IsAllDayEvent");
            if (isAllDayEvent != null) {
                bool tempIsAllDayEvent;
                if (Boolean.TryParse(isAllDayEvent, out tempIsAllDayEvent))
                    part.IsAllDayEvent = tempIsAllDayEvent;
            }

            var pattern = context.Attribute(part.PartDefinition.Name, "Pattern");
            if (pattern != null) {
                PatternType tempPattern;
                if (Enum.TryParse<PatternType>(pattern, out tempPattern))
                    part.Pattern = tempPattern;
            }

            var periodSpan = context.Attribute(part.PartDefinition.Name, "PeriodSpan");
            if (periodSpan != null) {
                int tempPeriodSpan;
                if (Int32.TryParse(periodSpan, out tempPeriodSpan))
                    part.PeriodSpan = tempPeriodSpan;
            }

            var dayOfPeriod = context.Attribute(part.PartDefinition.Name, "DayOfPeriod");
            if (dayOfPeriod != null) {
                int tempDayOfPeriod;
                if (Int32.TryParse(dayOfPeriod, out tempDayOfPeriod))
                    part.DayOfPeriod = tempDayOfPeriod;
            }

            var dayNames = context.Attribute(part.PartDefinition.Name, "DayNames");
            if (dayNames != null) {
                string[] dayNamesArray = dayNames.Split(',');
                part.DayNames = StaticCalendarServices.GetDayNameListFromArray(dayNamesArray);
            }

            var monthName = context.Attribute(part.PartDefinition.Name, "MonthName");
            if (monthName != null) {
                MonthNameType tempMonthName;
                if (Enum.TryParse<MonthNameType>(monthName, out tempMonthName))
                    part.MonthName = tempMonthName;
            }

            var recurrenceEnd = context.Attribute(part.PartDefinition.Name, "RecurrenceEnd");
            if (recurrenceEnd != null) {
                RecurrenceEndType tempRecurrenceEnd;
                if (Enum.TryParse<RecurrenceEndType>(recurrenceEnd, out tempRecurrenceEnd))
                    part.RecurrenceEnd = tempRecurrenceEnd;
            }

            var numberOccurrences = context.Attribute(part.PartDefinition.Name, "NumberOccurrences");
            if (numberOccurrences != null) {
                int tempNumberOccurrences;
                if (Int32.TryParse(numberOccurrences, out tempNumberOccurrences))
                    part.NumberOccurrences = tempNumberOccurrences;
            }

        }

        private void LoadViewModel(ref CalendarViewModel calendarViewModel, CalendarPart part) {
            if (part.Record != null) {
                calendarViewModel.EventOccurrence = part.EventOccurrence;
                calendarViewModel.EventOccurrenceList = _calendarService.GetEventOccurrenceList(part.EventOccurrence);
                calendarViewModel.StartDate = part.StartDate;
                calendarViewModel.StartTime = part.StartTime;
                calendarViewModel.EndDate = part.EndDate;
                calendarViewModel.EndTime = part.EndTime;
                calendarViewModel.IsAllDayEvent = part.IsAllDayEvent;
                calendarViewModel.Pattern = part.Pattern;
                calendarViewModel.PatternList = _calendarService.GetPatternList(part.Pattern);
                calendarViewModel.PeriodSpan = part.PeriodSpan;
                calendarViewModel.DayOfPeriod = part.DayOfPeriod;
                calendarViewModel.DayInstance = part.DayInstance;
                calendarViewModel.DayInstanceList = _calendarService.GetDayInstanceList(part.DayInstance);
                calendarViewModel.DayNamesArray = StaticCalendarServices.GetDayNameArrayFromList(part.DayNames);
                calendarViewModel.DayNameList = _calendarService.GetDayNameList(part.DayNames);
                calendarViewModel.MonthName = part.MonthName;
                calendarViewModel.MonthNameList = _calendarService.GetMonthNameList(part.MonthName);
                calendarViewModel.RecurrenceEnd = part.RecurrenceEnd;
                calendarViewModel.RecurrenceEndList = _calendarService.GetRecurrenceEndList(part.RecurrenceEnd);
                calendarViewModel.NumberOccurrences = part.NumberOccurrences;
            }
            else {
                calendarViewModel.EventOccurrenceList = _calendarService.GetEventOccurrenceList();
                calendarViewModel.PatternList = _calendarService.GetPatternList();
                calendarViewModel.DayInstanceList = _calendarService.GetDayInstanceList();
                calendarViewModel.DayNameList = _calendarService.GetDayNameList();
                calendarViewModel.MonthNameList = _calendarService.GetMonthNameList();
                calendarViewModel.RecurrenceEndList = _calendarService.GetRecurrenceEndList();
            }
        }

        private void LoadPart(ref CalendarPart part, CalendarViewModel calendarViewModel) {
            part.EventOccurrence = calendarViewModel.EventOccurrence;
            part.StartDate = calendarViewModel.StartDate;
            part.StartTime = calendarViewModel.StartTime;
            part.EndDate = calendarViewModel.EndDate;
            part.EndTime = calendarViewModel.EndTime;
            part.IsAllDayEvent = calendarViewModel.IsAllDayEvent;
            part.Pattern = calendarViewModel.Pattern;
            part.PeriodSpan = calendarViewModel.PeriodSpan;
            part.DayOfPeriod = calendarViewModel.DayOfPeriod;
            part.DayInstance = calendarViewModel.DayInstance;
            part.DayNames = StaticCalendarServices.GetDayNameListFromArray(calendarViewModel.DayNamesArray);
            part.MonthName = calendarViewModel.MonthName;
            part.RecurrenceEnd = calendarViewModel.RecurrenceEnd;
            part.NumberOccurrences = calendarViewModel.NumberOccurrences;
        }
    }
}